using System;
using System.Reflection;
using Microsoft.SPOT;

namespace NetduinoHappyHour.Util
{
    /// <summary>
    /// Helper to load and initialize objects, by their name
    /// </summary>
    public class ObjectFactory
    {
        public Object CreateObjectByNameAndParam(String ObjectDescription)
        {
            string commandName = null;
            string commandParamString = null;
            Type commandType = null;
            Type[] commandParameters = null;
            string[] commandSplit = null;
            int separatorIndex = -1;
            ConstructorInfo constructor = null;
            Object ObjectToExecute = null;

            // Trim empty constructor
            ObjectDescription = ObjectDescription.TrimEnd(new char[] { '(', ' ', ')' });
            // if constructor is not empty, strting brace is still there
            separatorIndex = ObjectDescription.IndexOf('(');

            if (separatorIndex > -1)
            {
                // name of object to be created
                commandName = ObjectDescription.Substring(0, separatorIndex);
                commandParamString = ObjectDescription.Substring(separatorIndex + 1);
                commandSplit = commandParamString.Split(new char[] { ',' });
                commandParameters = new Type[commandSplit.Length];
                for (int i = 0; i < commandSplit.Length; i++)
                {
                    commandParameters[i] = commandSplit[i].GetType();
                }
            }
            else
            {
                commandName = ObjectDescription;
                commandParameters = new Type[0];
            }

            commandType = Type.GetType(commandName);
            if (commandType == null)
            {
                Assembly a = Assembly.GetExecutingAssembly();
                Type[] types = a.GetTypes();
                foreach (Type type in types)
                {
                    if (type.Name.Equals(commandName))
                    {
                        commandType = type;
                        break;
                    }
                }
            }
            if (commandType == null)
            {
                return null;
            }
            else
            {
                constructor = commandType.GetConstructor(commandParameters);
            }

            if (constructor != null)
            {
                ObjectToExecute = constructor.Invoke(commandSplit);
            }

            return ObjectToExecute;
        }
    }
}
